package com.smallkingson.ylib.net.download;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;

import com.smallkingson.ylib.core.Yr;
import com.smallkingson.ylib.db.cache.YKey;

import org.apache.http.HttpStatus;

public class YDownloads {
	public static final String DOWNLOAD_PATH = Environment
			.getExternalStorageDirectory().getAbsolutePath() + "/downloads/";
	public static Map<String, YDownloadTask> taskMap = new LinkedHashMap<String, YDownloadTask>();
	public static ExecutorService downloadExecutorService = Executors
			.newCachedThreadPool();

	public static final int WHAT_DOWNLOAD_BEFORE = 0;
	public static final int WHAT_DOWNLOAD_UPDATE = 1;
	public static final int WHAT_DOWNLOAD_SUCCESS = 2;
	public static final int WHAT_DOWNLOAD_ERROR = 3;

	public static void init(Context context) {

	}

	public static void download(Context context, DownloadFile downloadFile,
			final DownloadListener downloadListener) {

		download(context, downloadFile, 3, downloadListener);
	}

	public static void download(final Context context,
			final DownloadFile downloadFile, final int threadCount,
			final DownloadListener downloadListener) {
		/*
		 * 下载任务中状态变化时与主线程通讯的桥梁
		 */
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case WHAT_DOWNLOAD_BEFORE: {
					Object[] objs = (Object[]) msg.obj;
					downloadListener.onInited((DownloadFile) objs[0]);
					break;
				}
				case WHAT_DOWNLOAD_UPDATE: {

					Object[] objs = (Object[]) msg.obj;
					downloadListener.onUpdate((DownloadFile) objs[0]);
					break;
				}
				case WHAT_DOWNLOAD_SUCCESS: {

					Object[] objs = (Object[]) msg.obj;
					DownloadFile df = (DownloadFile) objs[0];
					taskMap.remove(df.getUrl());
					YDownloadCacher.getInstance(context).cache(df);
					downloadListener.onSuccess(df);
					break;
				}
				case WHAT_DOWNLOAD_ERROR: {

					Object[] obj = (Object[]) msg.obj;
					DownloadFile df = (DownloadFile) obj[0];
					taskMap.remove(df.getUrl());
					downloadListener.onError(df, (Exception) obj[1]);
				}
					break;
				default:
					break;
				}
			}
		};
		/*
		 * 查看本地有没有该文件
		 */
		DownloadFile file = YDownloadCacher.getInstance(context).getCache(
				new YKey() {

					@Override
					public String getKey() {
						return downloadFile.getUrl();
					}
				});
		if (file != null) {
			file.from = From.CACHE;
			sendMessage(handler, WHAT_DOWNLOAD_SUCCESS, file);
			return;
		}
		// 查看此资源有没有正在下载
		YDownloadTask downloadTask = taskMap.get(downloadFile.getUrl());
		if (downloadTask == null) {
			if (downloadFile.getLocalPath() == null) {
				downloadFile.setLocalPath(DOWNLOAD_PATH);
			}
			downloadExecutorService.execute(new InitTask(context, downloadFile,
					handler) {
				@Override
				protected void onInited(Context context,
						DownloadFile downloadFile) {
					super.onInited(context, downloadFile);
					Yr.i("开始下载", downloadFile.getUrl(),
							downloadFile.getFileLength());
					YDownloadTask downloadTask = new YDownloadTask(context,
							handler, downloadFile, threadCount);
					// 避免重复下载
					taskMap.put(downloadFile.getUrl(), downloadTask);
					// 启动下载
					downloadTask.downLoad();
				}
			});
		} else {
			downloadTask.setHandler(handler);
		}
	}

	static class InitTask implements Runnable {
		DownloadFile downloadFile;
		private Context context;
		private Handler handler;

		public InitTask(Context context, DownloadFile downloadFile,
				Handler handler) {
			super();
			this.context = context;
			this.downloadFile = downloadFile;
			this.handler = handler;
		}

		@Override
		public void run() {

			HttpURLConnection connection = null;
			RandomAccessFile raf = null;

			try {
				URL url = new URL(downloadFile.getUrl());
				connection = (HttpURLConnection) url.openConnection();
				connection.setConnectTimeout(5000);
				connection.setRequestMethod("GET");
				int length = -1;
				if (connection.getResponseCode() == HttpStatus.SC_OK) {
					length = connection.getContentLength();
				}
				if (length <= 0) {
					return;
				}
				File dir = new File(downloadFile.getLocalPath());
				if (!dir.exists()) {
					dir.mkdir();
				}

				File file = new File(dir, downloadFile.getFileName());
				raf = new RandomAccessFile(file, "rwd");
				raf.setLength(length);
				downloadFile.setFileLength(length);
				onInited(context, downloadFile);
			} catch (Exception e) {
				sendMessage(handler, WHAT_DOWNLOAD_ERROR, downloadFile, e);
				Yr.logError(e);
			} finally {
				if (connection != null) {
					connection.disconnect();
				}
				if (raf != null) {
					try {
						raf.close();
					} catch (IOException e) {
						Yr.logError(e);
					}
				}
			}
		}

		protected void onInited(Context context, DownloadFile downloadFile) {
		}
	}

	public static interface DownloadListener {

		/**
		 * 读取到文件大小并准备开始下载时回调
		 * 
		 * @param downloadFile
		 */
		void onInited(DownloadFile downloadFile);

		/**
		 * 下载进度 可以通过downloadFile.getFinished获得
		 * 
		 * @param downloadFile
		 */
		void onUpdate(DownloadFile downloadFile);

		/**
		 * 下载成功回调
		 * 
		 * @param downloadFile
		 */
		void onSuccess(DownloadFile downloadFile);

		/**
		 * 下载失败
		 * 
		 * @param
		 */
		void onError(DownloadFile downloadFile, Exception e);

	}

	public static void sendMessage(Handler handler, int what, Object... objs) {
		Message message = Message.obtain();
		message.what = what;
		message.obj = objs;
		handler.sendMessage(message);
	}

	public static enum From {
		CACHE, URL
	}
}
